{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit L10_modClassesAlerteAtt;

interface


uses Classes,
     modClasses,
     L05_modFlotteTracking,
     SysUtils,

     modBaseType,


     Windows,
     modCoreRecu,
     ESBDates,
     sFonctionsChaines,


     modSockUtils,


     modAlarmeAttaque,



     modProfilsForAttack;


type
     TPlayerGestionAlerteAtt = class(TPlayerFlotteTracking)
     private

        //
        // Alerte d'attaque
        //

        // date de dernier téléchargement de la page aperçu spécialement pour la
        // vérification d'attaque
        FAlerteAttaqueLastDL     : int64;


        // nombre d'erreur de socket, pour declencher une verification de la connexion internet
        FAlerteAttaqueVerifNbErreurSocket: integer;

        // même si la page aperçu est téléchargé hors du contexte
        // de la vérification, cette valeur détermine si on fait traiter
        // la liste des messages par le gestionnaire d'alerte d'attaque
        //FAlerteAlwaysDoIt        : boolean;

        // détermine si l'alerte d'attaque est activé (au niveau OnTimer)
        FAlerteAttaqueEnable     : boolean;

        // détermine si une vérification d'attaque est en cours, cela évite de faire
        // planter les sondages automatique
        FAlerteAttaqueVerificationEnCours: boolean;

        // prochaine date à vérifier si il y a des attaques
        FAlerteAttaqueNextDateToCheck: int64;

        // détermine si l'auto relogin est activé pour les alerte d'attaque
        // (pas l'évacuation de flotte)
        //FAlerteAttaqueAutoReloginEnable: boolean;

        // collection des attaques, et gestion des évènements (OnNewAttack et OnFinAttack)
        FAlerteAttaqueGestion    : TCollectionAlarmeAttack;


        procedure Init;

        function  MsgListTraiteAvecAlerteAttaque: integer;
        procedure IncrementNextDateToCheckAlerteAtt;

        function ProceedAlerteAttaqueVerif: integer;
        
     public
        // collection des attaques, et gestion des évènements (OnNewAttack et OnFinAttack)
        property AlerteAttaqueGestion    : TCollectionAlarmeAttack read FAlerteAttaqueGestion;

        // détermine si l'alerte d'attaque est activé (au niveau OnTimer)
        // La liste de message est toute fois tout le temps traité lors du téléchargement
        // de la page apercu
        property AlerteAttaqueEnable     : boolean                 read FAlerteAttaqueEnable write FAlerteAttaqueEnable;
        property AlerteAttNextDateChecking: int64                  read FAlerteAttaqueNextDateToCheck;


        function ProceedUpdateApercu(bOverrideURLAndReference: boolean = false): integer; override;


        // Pas la peine au login puisque la page apercu est dl, MAIS elle est
        // downloadée sans passer par ProceedUpdateApercu
        // par contre, c'est utile pour activer l'alerte d'attaque dès le login
        function ProceedLogin: integer; override;



        procedure OnTimer; override;

        constructor Create;
        destructor Destroy; override;


        procedure ShowInternal; override;

        procedure AlerteAttDebug(bOnlyExist: boolean);

     end;



implementation

uses gnugettext;

procedure TPlayerGestionAlerteAtt.AlerteAttDebug(bOnlyExist: boolean);
var i: integer;
    pe : PAlarmeAttack;
    CurrDate: int64;
begin

    if AlerteAttaqueGestion.Count > 0 then begin

       CurrDate := DateTimeToUnix(Now);

       for i := 0 to AlerteAttaqueGestion.Count - 1 do begin
           pe := AlerteAttaqueGestion.Items[i];


           if bOnlyExist and pe.FlotteExistePlus then begin
              Continue;
           end;

           DoDebug('uid.DateImpact = ' + IntToStr(pe.uid.DateImpact));
           DoDebug('uid.Location = ' + IntToStr(pe.uid.Location));

           DoDebug('Depart: ' + mbtPlanetLocationToStr(pe.Depart));
           DoDebug('Arrivee: ' + mbtPlanetLocationToStr(pe.Arrivee));

           DoDebug('Impact local: '  + IntToStr(pe.DateImpactLocal) + ' - dans ' + ESBDGetDureeStrings(pe.DateImpactLocal - CurrDate, true));
           DoDebug('Impact serveur: ' + IntToStr(pe.DateImpactServeur));

           DoDebug('Délai avant impact eva: ' + IntToStr(pe.DelaiAvantImpactEva));




           DoDebug('ConnuDepuis: ' + IntToStr(pe.ConnuDepuis) + ' depuis ' + ESBDGetDureeStrings(CurrDate - pe.ConnuDepuis, true));
           DoDebug('SignalBeepNb: ' + IntToStr(pe.SignalBeepNb));
           DoDebug('SignalMusiqueNb: ' + IntToStr(pe.SignalMusiqueNb));
           DoDebug('ProgramLauched: ' + IntToStr(iif(pe.ProgramLauched, 1, 0)));

           DoDebug('HumainSoccupeDuReste: ' + IntToStr(pe.HumainSoccupeDuReste));



           DoDebug('ScoreFlotteAQuai: ' + IntToStr(pe.ScoreFlotteAQuai));
           DoDebug('ScoreDefense: ' + IntToStr(pe.ScoreDefense));
           DoDebug('ScoreFlotteAttaquante: ' + IntToStr(pe.ScoreFlotteAttaquante));

           DoDebug('Vaisseaux attaquant: ' + pe.VaisseauxAttaquant);

           DoDebug('EvacuationAutomatique State: ' + IntToStr(Ord(pe.EvacuationAutomatique)));

  

           DoDebug('FlotteExistePlus: ' + IntToStr(iif(pe.FlotteExistePlus, 1, 0)));
           DoDebug('FlotteExistePlusNotified: ' + IntToStr(iif(pe.FlotteExistePlusNotified, 1, 0)));
           DoDebug('FlotteDateCancel: ' + IntToStr(pe.FlotteDateCancel) + ' - depuis ' + ESBDGetDureeStrings(CurrDate - pe.FlotteDateCancel, true));
           DoDebug('------------------');
       end;


    end else begin
        DoDebug(_('Aucune attaque'));

    end;

end;


procedure TPlayerGestionAlerteAtt.ShowInternal;
begin

        inherited ShowInternal;
        
        DoDebug('@@@@@ AlerteAttaque @@@@@');

        // date de dernier téléchargement de la page aperçu spécialement pour la
        // vérification d'attaque
        DoDebugInt('LastDL', FAlerteAttaqueLastDL);


        // nombre d'erreur de socket, pour declencher une verification de la connexion internet
        DoDebugInt('VerifNbErreurSocket', FAlerteAttaqueVerifNbErreurSocket);


        // même si la page aperçu est téléchargé hors du contexte
        // de la vérification, cette valeur détermine si on fait traiter
        // la liste des messages par le gestionnaire d'alerte d'attaque
        //FAlerteAlwaysDoIt        : boolean;

        // détermine si l'alerte d'attaque est activé (au niveau OnTimer)
        DoDebugInt('Enable', iif(FAlerteAttaqueEnable, 1, 0));



        // détermine si une vérification d'attaque est en cours, cela évite de faire
        // planter les sondages automatique
        DoDebugInt('VerificationEnCours', iif(FAlerteAttaqueVerificationEnCours, 1, 0));

        
        // prochaine date à vérifier si il y a des attaques
        DoDebugInt('NextDateToCheck', FAlerteAttaqueNextDateToCheck);


        // collection des attaques, et gestion des évènements (OnNewAttack et OnFinAttack)
        DoDebugInt('.Count', FAlerteAttaqueGestion.Count);

end;

function TPlayerGestionAlerteAtt.ProceedLogin: integer;
begin

    Result := inherited ProceedLogin;
    
    if Conf.AlerteAttEnableOnLogin then begin
       AlerteAttaqueEnable := True;
    end;


end;

procedure TPlayerGestionAlerteAtt.OnTimer;
begin
    inherited OnTimer;

    if IsLoggedAndCanDoSomething = false then begin
       exit;
    end;

    ProceedAlerteAttaqueVerif;

end;

constructor TPlayerGestionAlerteAtt.Create;
begin
    inherited Create;

    FAlerteAttaqueGestion := TCollectionAlarmeAttack.Create;

    Init;
end;

destructor TPlayerGestionAlerteAtt.Destroy;
begin
    FAlerteAttaqueGestion.Free;

    inherited Destroy;
end;

function TPlayerGestionAlerteAtt.ProceedUpdateApercu(bOverrideURLAndReference: boolean = false): integer;
begin

    Result := inherited ProceedUpdateApercu(bOverrideURLAndReference);


    if Result > 0 then begin
       MsgListTraiteAvecAlerteAttaque;

       if NoT(FAlerteAttaqueVerificationEnCours) then begin
          // c'était une vérification manuelle
          // on vérifie si il y a eut une nouvelle attaque pour diminuer l'intervalle
          // entre chaque vérification
          FAlerteAttaqueLastDL := DateTimeToUnix(Now);
          IncrementNextDateToCheckAlerteAtt;
       end;

    end;

end;

function TPlayerGestionAlerteAtt.ProceedAlerteAttaqueVerif: integer;
label lConnPerdu;
var //CurrDate: int64;
    iResult: integer;
    BackuDate:int64;
begin

    if NoT(FAlerteAttaqueEnable) then begin
       Result := 1;
       exit;
    end;
    
    Result := 0;

    (*
    // update: vérification déjà faite avant d'arriver ici
    if sockHTTP.State <> httpReady then begin
       {$IFDEF DEBUG}
           DoDebug('ProceedAlerteAttaqueVerif - Composant HTTP non prêt');
       {$ENDIF}

       exit;
    end;
    *)

(*
    if FJobOccupation <> jobpAucun then begin
       {$IFDEF DEBUG}
           DoDebug('ProceedAlerteAttaqueVerif - Un autre job est déjà en cours d''exécution');
       {$ENDIF}

       exit;
    end;
*)

    if curPlanete = nil then begin
       {$IFDEF DEBUG}
          DoDebug('ProceedAlerteAttaqueVerif - Aucune planète sélectionnée - LogIn non effectué peut-être');
       {$ENDIF}

       exit;
    end;


    // obtient la date actuelle
    // update: déjà fait lors de la dernière classé hérité
    LastCurrDate := DateTimeToUnix(Now);



    if (LastCurrDate > FAlerteAttaqueNextDateToCheck) then begin
        // met à jour la dernière date de vérification
        // car il se peut que l'on modifie l'intervalle de vérification, on
        // doit alors connaitre la dernière date de téléchargement
        BackuDate            := FAlerteAttaqueLastDL;
        FAlerteAttaqueLastDL := LastCurrDate;



       {$IFDEF DEBUG}
          DoDebug('ProceedAlerteAttaqueVerif - Vérification d''attaque ennemie');
       {$ENDIF}


       FAlerteAttaqueVerificationEnCours := true;
       iResult := ProceedUpdateApercu;
       FAlerteAttaqueVerificationEnCours := false;

        if iResult > 0 then begin

           FAlerteAttaqueVerifNbErreurSocket := 0;


           (*
           Update: le TRAITEMENT s'effectue toujours dans le menu apercu
           
           if FAlerteAlwaysDoIt = False then begin
              // la vérification ne s'est pas effectué dans ProceedUpdateApercu
              Result := MsgListTraiteAvecAlerteAttaque;


           end else begin
              // la vérification s'est déjà effectué dans ProceedUpdateApercu
              Result := 1;
           end;
           *)

           // obtient la prochaine date de vérification
           // uniquement si la vérification a réussie
           // l'incrémentation doit se faire APRES avoir analyser les messages
           // car on choisi entre l'intervalle normal et whenattacked
           IncrementNextDateToCheckAlerteAtt;


          {$IFDEF DEBUG}
             DoDebug('ProceedAlerteAttaqueVerif - Effectuée');
          {$ENDIF}



        end else if iResult = CNT_ERROR_SHOULD_RELOGIN then begin
           // doit se relogger

           {$IFDEF DEBUG}
              DoDebug('ProceedAlerteAttaqueVerif - Echouée - (Devrait s''auto relogger ?)');
           {$ENDIF}



        end else if iResult = CNT_ERROR_MUST_RELOGIN then begin
           // // on sait que l'on doit se relogger
           {$IFDEF DEBUG}
              DoDebug('ProceedAlerteAttaqueVerif - Echouée - (Doit s''auto relogger ?)');
           {$ENDIF}

           FAlerteAttaqueVerifNbErreurSocket := 0;




        end else if iResult = CNT_ERROR_SOCKET then begin
          {$IFDEF DEBUG}
             DoDebug('ProceedAlerteAttaqueVerif - Echouée - Erreur socket: ' + IntToStr(iResult));
          {$ENDIF}

          // on recommence dans une minutes
          FAlerteAttaqueLastDL := BackuDate + 60;

          Inc(FAlerteAttaqueVerifNbErreurSocket);

          if FAlerteAttaqueVerifNbErreurSocket > 4 then begin
             // vérifie si la connexion internet est toujours bonne
             // l'erreur de socket peut provenir d'un proxy

             if sockHTTP.Proxy <> '' then begin
                // le proxy est devenu invalide
                // MAIS il peut etre devenu invalide car la connexion internet a ete perdu

                if suConnecterSurInternetResolveMethod = false then begin
                   // la connexion a été perdu
                   goto lConnPerdu;

                end else begin
                   {$IFDEF DEBUG}
                      DoDebug('ProceedAlerteAttaqueVerif - Echouée - Le proxy n''est plus valide...');
                   {$ENDIF}

                end;


             end else begin
                // connexion directe
                // la conexion a du être perdu

                if suConnecterSurInternetResolveMethod = false then begin
                   // la connexion a été perdu
                   lConnPerdu:
                   {$IFDEF DEBUG}
                      DoDebug('ProceedAlerteAttaqueVerif - Echouée - La connexion a été perdue...');
                   {$ENDIF}
                end;

             end;

         
          end;

        end else if iResult = CNT_ERROR_FATAL then begin
           // erreur fatale
           // on stop tout
          {$IFDEF DEBUG}
             DoDebug('ProceedAlerteAttaqueVerif - Echouée - Erreur fatale: ' + IntToStr(iResult));
          {$ENDIF}


        end else if iResult = CNT_ERROR_PARSING then begin
           // erreur de parsing
          {$IFDEF DEBUG}
             DoDebug('ProceedAlerteAttaqueVerif - Echouée - Erreur parsing: ' + IntToStr(iResult));
          {$ENDIF}

          // une erreur de parsing signifie que la page a été téléchargé
          // ce n'est donc pas une erreur de socket
          FAlerteAttaqueVerifNbErreurSocket := 0;

        end else begin
          {$IFDEF DEBUG}
             DoDebug('ProceedAlerteAttaqueVerif - Echouée - Erreur: ' + IntToStr(iResult));
          {$ENDIF}

        end;


    end;

  
end;


procedure TPlayerGestionAlerteAtt.IncrementNextDateToCheckAlerteAtt;
var iRangeAleatoire: int64;
begin

    Randomize;

    // minutes
    // pas de "FAlerteCheckEveryHumanAdd + 1" dans le random
    // car après on ajoute des secondes pour être aléatoire
    if FAlerteAttaqueGestion.IsAttacked then begin

       {$IFDEF DEBUG}
          DoDebug('IncrementNextDateToCheckAlerteAtt - Attaque en cours... ');
       {$ENDIF}

       //iRangeAleatoire := FAlerteCheckEveryMinutesWhenAttacked + Random(FAlerteCheckEveryHumanAddWhenAttacked);
       iRangeAleatoire := Conf.AlerteAttVerifEveryMinutesWhenAttacked + Random(Conf.AlerteAttVerifHumanAddWhenAttacked);


    end else begin
       //iRangeAleatoire := FAlerteCheckEveryMinutesNormal + Random(FAlerteCheckEveryHumanAddNormal);
       iRangeAleatoire := Conf.AlerteAttVerifEveryMinutes + Random(Conf.AlerteAttVerifHumanAdd);


    end;

    // converti en secondes
    iRangeAleatoire := iRangeAleatoire * 60;

    // ajoute des secondes aléatoire pour faire plus réaliste
    iRangeAleatoire := iRangeAleatoire + Random(60);

    FAlerteAttaqueNextDateToCheck := FAlerteAttaqueLastDL + iRangeAleatoire;

       {$IFDEF DEBUG}
          DoDebug('IncrementNextDateToCheckAlerteAtt - Prochaine vérification: ' + DateTimeToStr(UnixToDateTime(FAlerteAttaqueNextDateToCheck)));
       {$ENDIF}
end;


function TPlayerGestionAlerteAtt.MsgListTraiteAvecAlerteAttaque: integer;
begin
     FAlerteAttaqueGestion.TraiteMsgList(cParsing.pApercu.MsgList);
     Result := 1;
end;

procedure TPlayerGestionAlerteAtt.Init;
begin
        //
        // Alerte d'attaque
        //

        FAlerteAttaqueGestion.Clear;

        FAlerteAttaqueLastDL     := 0;


        FAlerteAttaqueNextDateToCheck := 0;



        FAlerteAttaqueVerifNbErreurSocket := 0;

        FAlerteAttaqueVerificationEnCours := false;


        
end;

end.
